package com.zouxw.utils.json.utils;

import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;

/**
 * 历史管理器
 * 提供撤销/重做功能，支持操作历史记录和状态恢复
 * 
 * @author zouxw
 * @version 1.0
 */
public class HistoryManager {
    
    // ==================== 配置常量 ====================
    /** 最大历史记录数量 */
    private static final int MAX_HISTORY_SIZE = 50;
    
    // ==================== 实例变量 ====================
    /** 撤销历史栈 */
    private final Deque<HistoryState> undoStack;
    
    /** 重做历史栈 */
    private final Deque<HistoryState> redoStack;
    
    /** 当前状态 */
    private HistoryState currentState;
    
    /** 是否正在执行历史操作（避免循环） */
    private boolean isExecutingHistoryOperation;
    
    // ==================== 构造函数 ====================
    
    /**
     * 构造函数
     */
    public HistoryManager() {
        this.undoStack = new ArrayDeque<>();
        this.redoStack = new ArrayDeque<>();
        this.currentState = null;
        this.isExecutingHistoryOperation = false;
    }
    
    // ==================== 公共方法 ====================
    
    /**
     * 保存状态到历史记录
     * 
     * @param jsonContent JSON内容
     * @param description 操作描述
     */
    public void saveState(String jsonContent, String description) {
        if (isExecutingHistoryOperation) {
            return; // 避免在执行历史操作时保存状态
        }
        
        HistoryState newState = new HistoryState(jsonContent, description, System.currentTimeMillis());
        
        // 如果内容没有变化，不保存
        if (currentState != null && currentState.getJsonContent().equals(jsonContent)) {
            return;
        }
        
        // 保存当前状态到撤销栈
        if (currentState != null) {
            undoStack.push(currentState);
            
            // 限制历史记录数量
            if (undoStack.size() > MAX_HISTORY_SIZE) {
                // 移除最旧的历史记录
                Iterator<HistoryState> iterator = undoStack.descendingIterator();
                for (int i = 0; i < undoStack.size() - MAX_HISTORY_SIZE; i++) {
                    iterator.next();
                    iterator.remove();
                }
            }
        }
        
        // 清空重做栈
        redoStack.clear();
        
        // 设置新状态为当前状态
        currentState = newState;
    }
    
    /**
     * 撤销操作
     * 
     * @return 撤销后的状态，如果没有可撤销的操作返回null
     */
    public HistoryState undo() {
        if (undoStack.isEmpty()) {
            return null;
        }
        
        isExecutingHistoryOperation = true;
        
        try {
            // 将当前状态移到重做栈
            if (currentState != null) {
                redoStack.push(currentState);
            }
            
            // 从撤销栈获取上一个状态
            HistoryState previousState = undoStack.pop();
            currentState = previousState;
            
            return previousState;
        } finally {
            isExecutingHistoryOperation = false;
        }
    }
    
    /**
     * 重做操作
     * 
     * @return 重做后的状态，如果没有可重做的操作返回null
     */
    public HistoryState redo() {
        if (redoStack.isEmpty()) {
            return null;
        }
        
        isExecutingHistoryOperation = true;
        
        try {
            // 将当前状态移到撤销栈
            if (currentState != null) {
                undoStack.push(currentState);
            }
            
            // 从重做栈获取下一个状态
            HistoryState nextState = redoStack.pop();
            currentState = nextState;
            
            return nextState;
        } finally {
            isExecutingHistoryOperation = false;
        }
    }
    
    /**
     * 检查是否可以撤销
     * 
     * @return 是否可以撤销
     */
    public boolean canUndo() {
        return !undoStack.isEmpty();
    }
    
    /**
     * 检查是否可以重做
     * 
     * @return 是否可以重做
     */
    public boolean canRedo() {
        return !redoStack.isEmpty();
    }
    
    /**
     * 获取撤销操作的描述
     * 
     * @return 撤销操作描述
     */
    public String getUndoDescription() {
        if (undoStack.isEmpty()) {
            return null;
        }
        return undoStack.peek().getDescription();
    }
    
    /**
     * 获取重做操作的描述
     * 
     * @return 重做操作描述
     */
    public String getRedoDescription() {
        if (redoStack.isEmpty()) {
            return null;
        }
        return redoStack.peek().getDescription();
    }
    
    /**
     * 清空历史记录
     */
    public void clear() {
        undoStack.clear();
        redoStack.clear();
        currentState = null;
    }
    
    /**
     * 获取历史记录统计信息
     * 
     * @return 统计信息
     */
    public HistoryStatistics getStatistics() {
        return new HistoryStatistics(undoStack.size(), redoStack.size(), currentState != null);
    }
    
    // ==================== 内部类 ====================
    
    /**
     * 历史状态类
     */
    public static class HistoryState {
        private final String jsonContent;
        private final String description;
        private final long timestamp;
        
        public HistoryState(String jsonContent, String description, long timestamp) {
            this.jsonContent = jsonContent;
            this.description = description;
            this.timestamp = timestamp;
        }
        
        public String getJsonContent() { return jsonContent; }
        public String getDescription() { return description; }
        public long getTimestamp() { return timestamp; }
        
        @Override
        public String toString() {
            return String.format("%s (%s)", description, 
                    new java.util.Date(timestamp).toString());
        }
    }
    
    /**
     * 历史统计信息类
     */
    public static class HistoryStatistics {
        private final int undoCount;
        private final int redoCount;
        private final boolean hasCurrentState;
        
        public HistoryStatistics(int undoCount, int redoCount, boolean hasCurrentState) {
            this.undoCount = undoCount;
            this.redoCount = redoCount;
            this.hasCurrentState = hasCurrentState;
        }
        
        public int getUndoCount() { return undoCount; }
        public int getRedoCount() { return redoCount; }
        public boolean hasCurrentState() { return hasCurrentState; }
        
        @Override
        public String toString() {
            return String.format("撤销: %d, 重做: %d, 当前状态: %s", 
                    undoCount, redoCount, hasCurrentState ? "有" : "无");
        }
    }
}
